#pragma once

namespace xtd {

template <typename T>
struct type_traits;

/// type::traits<T>::accumulator_type - type for storing of sums, sums of squares, etc.
/// type::traits<T>::real_type - type for storing means, dispersions, etc.
/// type::traits<T>::element_type - T for simple types, type of element for vector and other complex objects

template <>
struct type_traits<bool> { 
	typedef int accumulator_type;
	typedef float real_type;
	typedef bool element_type;
};

template <>
struct type_traits<signed char> { 
	typedef signed int accumulator_type;
	typedef float real_type;
	typedef signed char element_type;
};

template <>
struct type_traits<unsigned char> { 
	typedef unsigned int accumulator_type;
	typedef float real_type;
	typedef unsigned char element_type;
};

template <>
struct type_traits<signed short> { 
	typedef signed int accumulator_type;
	typedef float real_type;
	typedef signed short element_type;
};

template <>
struct type_traits<unsigned short> { 
	typedef unsigned int accumulator_type;
	typedef float real_type;
	typedef unsigned short element_type;
};

template <>
struct type_traits<int> { 
	typedef long long int accumulator_type;
	typedef float real_type;
	typedef int element_type;
};

template <>
struct type_traits<unsigned> { 
	typedef long long unsigned accumulator_type;
	typedef float real_type;
	typedef unsigned element_type;
};

template <>
struct type_traits<float> { 
	typedef double accumulator_type;
	typedef float real_type;
	typedef float element_type;
};

template <>
struct type_traits<double> { 
	typedef double accumulator_type;
	typedef double real_type;
	typedef double element_type;
};

} //namespace xtd
